/*
 * ChaptersWithAnchorFinder.java
 *
 *  created: 20.8.2011
 *  charset: UTF-8
 *  license: MIT (X11) (See LICENSE file for full license)
 */
package cz.mp.k3bg.core;

import cz.mp.k3bg.log.LoggerManager;
import cz.mp.util.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

// TODO ^ vymyslet lepší a hezčí způsob jak udělat ChaptersWithAnchorFinder

/**
 * Třída {@code ChaptersWithAnchorFinder} hledá kapitoly v HTML
 * (tagy {@literal H1 - H6}), na které vede odkaz.
 * 
 * @author Martin Pokorný
 * @version 0.1
 * @see ChapterWithAnchor
 * @see TocGenerator
 */
public class ChaptersWithAnchorFinder {

    private static final boolean DEBUG = false;
    private static final Logger logger =
            LoggerManager.getLogger(ChaptersWithAnchorFinder.class, DEBUG);
    
    private HtmlFile srcFile;
    
    private static final int DEFAULT_LEVEL = 3;
    
    /** Hledá kotvy k {@literal H1 - H<level>}. */
    private int level = DEFAULT_LEVEL;
            
    /** Seznam nalezených kapitol s kotvou. */
    // (je potřeba mít informace o:  pořadí v souboru, level H, jméno kotvy)
    private ArrayList<ChapterWithAnchor> chaptersWithAnchor = 
            new ArrayList<ChapterWithAnchor>();
    
    /**
     * Vzor pro hledání kapitol s kotvami (nepěkná zlá věc).
     * Není spolehlivé(!).
     * ('~~~~' je nahrazeno za výčet úrovní, pro které hledat 
     *  (např '123' pro H1-H3) )
     * <p>
     * pozn: <a href="http://www.regexplanet.com/simple/index.html">
     * regexplanet</a>
     */
    private static String ANCHOR_PATTERN_PATTERN =
            "<[aA]\\s+[^\\s]*\\s*name=[\"']?([^\\s\"']*)[\"']?\\s*[^\\/>\\s]*\\s*\\/>\\s*<[hH][~~~~][^>]*>\\s*(.*)\\s*</[hH]([~~~~])>|" +
            "<[aA]\\s+[^\\s]*\\s*name=[\"']?([^\\s\"']*)[\"']?\\s*[^\\/>\\s]*\\s*>\\s*</[aA]>\\s*<[hH][~~~~][^>]*>\\s*(.*)\\s*</[hH]([~~~~])>|" +
            "<[aA]\\s+[^\\s]*\\s*name=[\"']?([^\\s\"']*)[\"']?\\s*[^\\/>\\s]*\\s*>\\s*<[hH][~~~~][^>]*>\\s*(.*)\\s*</[hH]([~~~~])>\\s*</[aA]>|" +
            "<[hH][~~~~][^>]*>\\s*<[aA]\\s+[^\\s]*\\s*name=[\"']?([^\\s\"']*)[\"']?\\s*[^\\/>\\s]*\\s*>(.*)\\s*</[aA]>\\s*</[hH]([~~~~])>|" +
            "<[hH][~~~~][^>]*>\\s*<[aA]\\s+[^\\s]*\\s*name=[\"']?([^\\s\"']*)[\"']?\\s*[^\\/>\\s]*\\s*\\/>(.*)\\s*</[hH]([~~~~])>";
    
    /**
     * Generováno z ANCHOR_PATTERN_PATTERN viz 
     * {@linkplain #generateAnchorPattern() }
     */
    private String anchorPattern = null;
    
    
    // -----
    
    /** */
    public ChaptersWithAnchorFinder(HtmlFile srcFile) throws IOException {
        setLevelImpl(DEFAULT_LEVEL);
        
        if (srcFile == null) {
            throw new IllegalArgumentException("srcFile=null");
        }
        this.srcFile = srcFile;
    }

    /**
     * 
     * @return 
     */
    public TextFile getSrcFile() {
        return srcFile;
    }
    
    

    /**
     * 
     * @param tocLevel 
     */
    public void setLevel(int tocLevel) {
        setLevelImpl(tocLevel);
    }

    /**
     * 
     * Voláno konstruktorem.
     * 
     * @param tocLevel 
     */
    private void setLevelImpl(int tocLevel) {
        logger.config("tocLevel = " + tocLevel);
        if (tocLevel > 6 || tocLevel < 1) {
            throw new IllegalArgumentException("tocLevel: 1-6");
        }
        this.level = tocLevel;
        generateAnchorPattern();
    }
        
    /**
     * 
     * @return 
     */
    public int getLevel() {
        return level;
    }
    
    /**
     * 
     * 
     */
    private void generateAnchorPattern() {
        logger.finer("");
        StringBuilder levels = new StringBuilder();        
        for (int i=1; i<=level; i++) {
            levels.append(i);            
        }
        
        anchorPattern = ANCHOR_PATTERN_PATTERN
                .replaceAll("~~~~", levels.toString()); 
    }


    /**
     * 
     * 
     */
    public ArrayList<ChapterWithAnchor> find() throws IOException {
        logger.info("");
        if (StringUtils.isBlank(anchorPattern)) {
            throw new IllegalStateException("anchorPattern is empty");
        } 
                
        String srcText = srcFile.readFileToString();
        
        Pattern pattern = Pattern.compile(anchorPattern);        
        Matcher matcher = pattern.matcher(srcText);
        
        while (matcher.find()) {
            String anchorName = "";
            String chapterName = "";
            int hLevel = 0;
            for (int i=1; i<=matcher.groupCount()-2; i++) {
                if (matcher.group(i) != null) {
                    // vždy (pro všechny části regexpu) v   
                    //    pořadí:  anchorName  chapterName  hLevel                    
                    
                    anchorName = matcher.group(i);
                    chapterName = matcher.group(i+1);
                    hLevel = Integer.valueOf(matcher.group(i+2));
                    
                    ChapterWithAnchor cha = new ChapterWithAnchor(
                            chapterName, anchorName, hLevel);
                    chaptersWithAnchor.add(cha);
                    logger.finer("add : " + cha);
                    
                    break;
                }
                else {
                    logger.finer("no  anchorName,chapterName,hLevel");
                }
            }
        }
        
        return getChaptersWithAnchor();
    }

    /**
     * 
     * @return 
     */
    public ArrayList<ChapterWithAnchor> getChaptersWithAnchor() {
        return new ArrayList<ChapterWithAnchor>(chaptersWithAnchor);
    }

}   // ChaptersWithAnchorFinder
